pub trait Draw {
    // 在 Rust 的 trait 方法定义中，通常需要指定接收者（self、&self 或 &mut self），
    // 以明确方法如何访问实现该 trait 的类型实例。
    // 如果不写接收者，编译器无法确定方法如何与具体的实例进行交互和访问其数据。
    fn draw(&self);
}

pub struct Screen {
    // components是一个集合, 集合里包含了实现了Draw这个trait的类型
    pub components: Vec<Box<dyn Draw>>
}

impl Screen {
    // 使用 &self 可以避免复制整个 Screen 对象，从而提高性能和减少内存开销。通过引用，run 方法能够访问和操作原始的 Screen 对象，而无需创建其副本
    pub fn run(&self) {
        for component in self.components.iter() {
            component.draw();
        }
    }
}

// 想想为何不用泛型呢, 如果采用以下方式, 那么, Vec中就只有一个类型了
// pub struct Screen<T: Draw> {
//     components: Vec<T>
// }

pub struct Button {
    pub width: i32,
    pub height: i32,
    pub label: String
}

impl Draw for Button {
    fn draw(&self) {
        println!("this is Button, width: {}; height: {}, label: {}", self.width, self.height, self.label);
    }
}